package com.kylin.common.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import java.util.Locale;

import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.criterion.Order;

import com.kylin.common.dict.ISelectOption;
import com.kylin.common.dict.orm.CatDict;
import com.kylin.common.dict.orm.Dict;
import com.kylin.common.entity.SelectOption;
import com.kylin.common.exception.BusinessException;
import com.kylin.common.exception.SystemException;
import com.kylin.hibernate.BaseHibernateDAO;
import com.kylin.hibernate.CriteriaInfo;
import com.kylin.hibernate.PropertyCondition;
import com.kylin.module.ad.business.ADBlogic;
import com.kylin.module.ad.orm.ADType;

public class MemObjFactory {
	protected static Logger log = Logger.getLogger(MemObjFactory.class);

	/** 所有的行业类别列表,以系统语言类别为key，分类存放List */
	public static Hashtable adminMenus = new Hashtable();

	public static Locale[] SysLocales = new Locale[] { new Locale("zh", "CN"),
			new Locale("en", "US"), new Locale("ru", "RU"), new Locale("de", "DE"),
			new Locale("ko", "KR"), new Locale("ja", "JP"), };

	/** 本系统支持的语言列表,以系统语言类别为key，分类存放List */
	public static Hashtable SysLanguageMap = new Hashtable();

	/** 所有的语言列表,以系统语言类别为key，分类存放List */
	public static Hashtable AllLanguageMap = new Hashtable();

	/** 所有的国家地区列表,以系统语言类别为key，分类存放List */
	public static Hashtable AllCountryMap = new Hashtable();

	/** 所有的属性字典列表,以属性名和系统语言为key，分类存放List */
	public static Hashtable DictMap = new Hashtable();

	/**
	 * 取得当前系统支持的语言列表 初始化时把语言列表整理成下拉菜单格式的列表放入内存
	 * 
	 * @param locale
	 * @return
	 */
	public static List getSysLanguageList(Locale locale) {
		if(locale == null){
			locale = Locale.getDefault();
			log.error("取当前系统支持的语言,没有传入正确的Locale ，使用系统缺省 "+locale);
		}
		List SysLanguageList = (List) SysLanguageMap.get(locale.toString());
		if (SysLanguageList == null) {
			SysLanguageList = new ArrayList();
			for (int i = 0; i < SysLocales.length; i++) {
				String languageLabel = SysLocales[i].getDisplayLanguage(locale);
				String languageValue = SysLocales[i].toString();
				if (languageLabel == null || "".equals(languageLabel))
					continue;
				ISelectOption vbean = new SelectOption(languageValue, languageLabel);
				SysLanguageList.add(vbean);
			}
			SysLanguageMap.put(locale.toString(), SysLanguageList);
			log.info("数据加载完成：将 [系统支持的语言列表]（" + locale + "） 到内存中");
		}
		return SysLanguageList;
	}

	/**
	 * 取得所有语言列表 初始化时把语言列表整理成下拉菜单格式的列表放入内存
	 * 
	 * @param locale
	 * @return
	 */
	public static List getAllLanguageList(Locale locale) {
		List AllLanguageList = (List) AllLanguageMap.get(locale.toString());
		if (AllLanguageList == null) {
			Locale[] locales = Locale.getAvailableLocales();
			AllLanguageList = new ArrayList();
			for (int i = 0; i < locales.length; i++) {
				String label = locales[i].getDisplayName(locale);
				String value = locales[i].toString();
				if(value.indexOf("_") < 1)
					continue;
				SelectOption vbean = new SelectOption(value, label);
				AllLanguageList.add(vbean);
			}
			AllLanguageMap.put(locale.toString(), AllLanguageList);
			log.info("数据加载完成：将 [所有语言列表]（" + locale + "） 载入到内存中");
		}
		return AllLanguageList;
	}

	/**
	 * 取得所有国家地区列表 初始化时把国家列表整理成下拉菜单格式的列表放入内存
	 * 
	 * @param locale
	 * @return
	 */
	public static List getAllCountryList(Locale locale) {
		if(locale == null)
			locale = UTool.getLocaleByLang("zh_CN");
		List AllCountryList = (List) AllCountryMap.get(locale.toString());
		if (AllCountryList == null) {
			Locale[] locales = Locale.getAvailableLocales();
			//java.util.Arrays.(locales);
			AllCountryList = new ArrayList();
			for (int i = 0; i < locales.length; i++) {
				String label = locales[i].getDisplayCountry(locale);
				String value = locales[i].toString();
				if(label == null || label.equals(""))
					continue;
				if(value == null || value.equals("") || value.length() > 6)
					continue;
				SelectOption vbean = new SelectOption(value, label);
				AllCountryList.add(vbean);
			}
			
			AllCountryMap.put(locale.toString(), AllCountryList);
			log.info("数据加载完成：将 [所有国家地区列表]（" + locale + "） 载入到内存中");
		}
		return AllCountryList;
	}

	/**
	 * 加载数据库中的属性字典数据到内存 
	 */
	public static void loadDicts(){
		try {
			List catList = BaseHibernateDAO.findAll(CatDict.class, null);
			if (catList != null) {
				for (int i = 0; i < catList.size(); i++) {
					CatDict cat = (CatDict) catList.get(i);
					loadDictByCat(cat);
				}
			}
		} catch (Exception e) {
			log.error("加载属性字典表出错：" + e, e);
		}
	}

	/**
	 * 按属性字典类别从数据库载入数据到内存
	 * @param cat
	 * @throws HibernateException
	 * @throws BusinessException
	 */
	private static void loadDictByCat(CatDict cat) throws HibernateException, BusinessException{
		for(int i=0;i<MemObjFactory.SysLocales.length;i++){
			loadDictByCatLang( cat,SysLocales[i].toString());
		}
	}
	private static void loadDictByCatLang(CatDict cat,String language) throws HibernateException, BusinessException{
		DictMap.put(cat.getName() + language, new ArrayList());
		PropertyCondition[] pConditions = new PropertyCondition[] {
				new PropertyCondition("catdict", cat,
						PropertyCondition.OPERATOR_EQ),
				new PropertyCondition("language", language,
						PropertyCondition.OPERATOR_EQ) };
		CriteriaInfo cinfo = new CriteriaInfo(Dict.class, pConditions, Order
					.asc("ordering"));
		List list = BaseHibernateDAO.getCriteriaFromInfo(cinfo).list();
		DictMap.put(cat.getName() + language, list);
		log.info("载入属性字典表：" + cat.getName() + "("+language+")");
	}	
	
	/**
	 * 按属性字典名和语言种类 取得字典所有选项
	 * @param catName  属性字典名，在dictName.jsp中注册
	 * @param language
	 * @return
	 */
	public static List getDict(String catName, String language) {
		log.debug("getDict("+catName+" , "+language+")");
		String dictName = catName + language;
		Enumeration enu = DictMap.keys();
		boolean hasName = false;
		while(enu.hasMoreElements()){
			if(enu.nextElement().equals(dictName))
				hasName = true;
		}
		if(hasName == false){
			log.error("系统中未找到名为 "+catName+"("+language+") 的属性字典");
			return new ArrayList();
			//throw new SystemException("系统中未找到名为 "+catName+"("+language+") 的属性字典");
		}
		List list = (List) DictMap.get(dictName);
		return list;
	}
	
	/**
	 * 按属性字典名取得字典所有选项(所有语言种类)
	 * @param catName  属性字典名，在dictName.jsp中注册
	 * @param language
	 * @return
	 */
	public static List getDict(String catName) {
		log.debug("getDict("+catName+")");
		List allLanguageList = new java.util.LinkedList();
		for (int i = 0; i < SysLocales.length; i++) {
			String dictName = catName + SysLocales[i].toString();
			List list = (List) DictMap.get(dictName);
			if(list != null)
				allLanguageList.addAll(list);
		}
		return allLanguageList;
	}

	/**
	 * 重新加载属性字典，刷新内存中数据
	 * @param catName
	 * @param language
	 * @throws BusinessException 
	 * @throws HibernateException 
	 */
	static public void reloadDict(CatDict cat) throws HibernateException, BusinessException {
		log.info("重新加载属性字典 "+ cat.getName());
		if (DictMap.get(cat.getName() + cat.getLanguage()) != null)
			DictMap.remove(cat.getName() + cat.getLanguage());
		loadDictByCat(cat);
	}

	/**
	 * 翻译属性字典名，传入属性项的值 返回属性项名称
	 * @param id
	 * @return
	 * @throws NumberFormatException
	 * @throws BusinessException
	 */
	static public String getDictName(Long id) throws NumberFormatException,
			BusinessException {
		Collection co = DictMap.values();
		List[] allList = (List[]) co.toArray(new List[0]);
		if (allList != null) {
			for (int i = 0; i < allList.length; i++) {
				for (int j = 0; j < allList[i].size(); j++) {
					Dict dict = (Dict) allList[i].get(j);
					if (dict.getId().equals(id))
						return dict.getName();
				}
			}
		}
		return null;
	}
	static public Hashtable ADs = new Hashtable();
	/**
	 * 将指定广告类型和语言种类的广告加载到内存中
	 * @param typeMark  指定广告类型标识符
	 * @param language  广告所属语言种类
	 * @return
	 * @throws BusinessException
	 */
	static public ADType getADType(String typeMark,String language) throws BusinessException{
		ADType adType;
		if(ADs.get(typeMark+language) == null){
			adType = new ADBlogic().getADTypeADs(typeMark, language);
		    ADs.put(typeMark+language, adType);
		}else
			adType = (ADType)ADs.get(typeMark+language);
		return adType;
	}
	
	/**
	 * 重载内存中的广告
	 * 一般当广告发生增删或修改，都需要调此方法更新内存
	 * @param typeMark
	 * @param language
	 * @throws BusinessException
	 */
	static public void reloadAD(String typeMark,String language) throws BusinessException{
		log.debug("重载内存中的广告: "+typeMark+", "+language);
		ADType adType = new ADBlogic().getADTypeADs(typeMark, language);
		    ADs.put(typeMark+language, adType);
	}
}
